home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / CTOOLS10.ARJ / RANDOM.C < prev    next >
C/C++ Source or Header  |  1991-12-31  |  5KB  |  179 lines

  1. /****************************************************************************
  2. *
  3. *                    Copyright (C) 1991 Kendall Bennett.
  4. *                            All rights reserved.
  5. *
  6. * Filename:        $RCSfile: random.c $
  7. * Version:        $Revision: 1.3 $
  8. *
  9. * Language:        ANSI C
  10. * Environment:    any
  11. *
  12. * Description:    A module to produce random number in many different
  13. *                formats. The numbers are produces using the linear
  14. *                congruential method. The routines are all based on
  15. *                long integers (32 bits on an IBM PC), so the
  16. *                computation is not as efficient as it could be for the
  17. *                IBM PC environment. We could recode it using 16 bit
  18. *                integers to speed it up, but at present that is
  19. *                unneeded.
  20. *
  21. * $Id: random.c 1.3 91/12/31 19:40:21 kjb Exp $
  22. *
  23. * Revision History:
  24. * -----------------
  25. *
  26. * $Log:    random.c $
  27. * Revision 1.3  91/12/31  19:40:21  kjb
  28. * Modified include file directories
  29. * Revision 1.2  91/09/03  18:28:22  ROOT_DOS
  30. * Ported to UNIX.
  31. * Revision 1.1  91/08/16  10:54:35  ROOT_DOS
  32. * Initial revision
  33. ****************************************************************************/
  34.  
  35. #include <stdio.h>
  36. #include <malloc.h>
  37. #include "random.h"
  38.  
  39. /*------------------------- Global variables ------------------------------*/
  40.  
  41. static long    seed;                    /* Seed for random number generator    */
  42.  
  43. /*-------------------------- Implementation -------------------------------*/
  44.  
  45. #define    M    100000000L                /* Special 'magic' values required    */
  46. #define    M1    10000L                    /* by the random number routines.    */
  47. #define    B    31415821L
  48.  
  49. void randinit(long s)
  50. /****************************************************************************
  51. *
  52. * Function:        randinit
  53. * Parameters:    long    seed    -    Number to seed generator with.
  54. * Returns:        Nothing.
  55. *
  56. * Description:    Seed the random number generator.
  57. *
  58. ****************************************************************************/
  59. {
  60.     seed = s;
  61. }
  62.  
  63. static long mult(long p,long q)
  64. /****************************************************************************
  65. *
  66. * Function:        mult
  67. * Parameters:    long    p    - First number to multiply
  68. *                long    q    - Second number to multiply
  69. * Returns:        Result of the multiplication.
  70. *
  71. * Description:    Multiplies two large numbers together by breaking it into
  72. *                pieces, and ignoring any overflow produced.
  73. *
  74. ****************************************************************************/
  75. {
  76.     long    p1,p0,q1,q0;
  77.  
  78.     p1 = p / M1;    p0 = p % M1;
  79.     q1 = q / M1;    q0 = q % M1;
  80.     return (((p0 * q1 + p1 * q0) % M1) * M1 + p0 * q0) % M;
  81. }
  82.  
  83. long randomlong(long range)
  84. /****************************************************************************
  85. *
  86. * Function:        randomlong
  87. * Parameters:    None.
  88. * Returns:        A psuedo-random number in the range 0-'range'.
  89. *
  90. * Description:    random generates a psuedo-random number between 0 and
  91. *                'range'.
  92. *
  93. ****************************************************************************/
  94. {
  95.     seed = (mult(seed,B) + 1) % M;
  96.     return ((seed/M1) * range) / M1;
  97. }
  98.  
  99. double randomfloat(void)
  100. /****************************************************************************
  101. *
  102. * Function:        randomfloat
  103. * Parameters:    None.
  104. * Returns:        A psuedo-random number in the range 0-1.
  105. *
  106. * Description:    randomfloat generates a psuedo-random number between
  107. *                0 and 1.
  108. *
  109. ****************************************************************************/
  110. {
  111.     seed = (mult(seed,B) + 1) % M;
  112.     return (double)seed/(double)M;
  113. }
  114.  
  115. double chisquare(int N,int r,long s)
  116. /****************************************************************************
  117. *
  118. * Function:        chisquare
  119. * Parameters:    int        N    - Number of iterations to complete (at least
  120. *                              10*r)
  121. *                int        r    - Range of numbers to test
  122. *                long    s    - The seed value for the test.
  123. * Returns:        A floating point number equal to the chisquared value.
  124. *
  125. * Description:    Computes the chisquared value for the floating point number
  126. *                generator in this package for debugging purposes. This
  127. *                value should be within 20% of the value specified for r,
  128. *                and the test should be completed at least 10 times, since
  129. *                the computation could be wrong 1 out of 10 times.
  130. *
  131. ****************************************************************************/
  132. {
  133.     int        i;
  134.     long    t;
  135.     long    *f;
  136.  
  137.     if ((f = (long *)malloc(sizeof(long) * r)) == NULL) {
  138.         fprintf(stderr,"Not enough memory: chisquare\n");
  139.         exit(1);
  140.         }
  141.     randinit(s);
  142.     for (i = 0; i < r; i++)
  143.         f[i] = 0;
  144.     for (i = 0; i < N; i++)
  145.         f[(int)randomlong(r)]++;
  146.     for (i = 0, t = 0; i < r; i++)
  147.         t += f[i]*f[i];
  148.     free(f);
  149.     return ((r * (double)t/N) - N);
  150. }
  151.  
  152. #ifdef    TESTING
  153.  
  154. void main(void)
  155. {
  156.     int        r,i,percent,final;
  157.     float    chi;
  158.  
  159.     r = 100;
  160.     final = 0;
  161.     for (i = 0; i < 10; i++) {
  162.         chi = chisquare(10*r,r,time(NULL));
  163.         percent = abs(100 - (int)(chi * 100 / r));
  164.         printf("%-2d - Range: %4d -> Chisquare: %f (%d%%)\n",i+1,r,chi,percent);
  165.         r += 100;
  166.         final += percent;
  167.         }
  168.     final /= (i + 1);            /* Determine average percentage            */
  169.     if (final < 20)
  170.         printf("\nRandom number routine is good (averaged %d%% proximity to 'range')\n",final);
  171.     else
  172.         printf("\nRandom number routine is bad (averaged %d%% proximity to 'range')\n",final);
  173. }
  174.  
  175. #endif
  176.